﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace ProjectPheonix {
    class EntityManager : DrawableGameComponent {
        List<BasicEntity> models = new List<BasicEntity>();
        List<BasicEntity> shots = new List<BasicEntity>();

        Vector3 bulletPosMAX = new Vector3(100, 100, 100);
        Vector3 bulletPosMIN = new Vector3(-100, -100, -100);

        List<ParticleExplosion> explosions = new List<ParticleExplosion>();
        ParticleExplosionSettings particleExplosionSettings = new ParticleExplosionSettings();
        ParticleSettings particleSettings = new ParticleSettings();
        Texture2D explosionTexture;
        Texture2D explosionColorsTexture;
        Effect explosionEffect;

        ParticleStarSheet stars;
        Effect starEffect;
        Texture2D starTexture;

        public EntityManager(Game game)
            : base(game) {

        }

        public override void Initialize() {
            base.Initialize();
        }

        public void addEntity(BasicEntity be) {
            models.Add(be);
        }

        protected override void LoadContent() {
            explosionTexture = Game.Content.Load<Texture2D>(@"Textures\Particle");
            explosionColorsTexture = Game.Content.Load<Texture2D>(@"Textures\ParticleColors");
            explosionEffect = Game.Content.Load<Effect>(@"effects\particle");

            // Set effect parameters that don't change per particle
            explosionEffect.CurrentTechnique = explosionEffect.Techniques["Technique1"];
            explosionEffect.Parameters["theTexture"].SetValue(explosionTexture);

            // Load star texture and effect
            starTexture = Game.Content.Load<Texture2D>(@"textures\stars");
            starEffect = explosionEffect.Clone();
            starEffect.CurrentTechnique = starEffect.Techniques["Technique1"];
            starEffect.Parameters["theTexture"].SetValue(explosionTexture);

            // Initialize particle star sheet
            stars = new ParticleStarSheet(
                GraphicsDevice,
                new Vector3(2000, 2000, -1900),
                1500, starTexture,
                particleSettings,
                starEffect);

            models.Add(new BasicEntity(
                Game.Content.Load<Model>(@"models\stmedard"), new Vector3(0, -18, -100), .1f));
            models.Add(new BasicEntity(
                Game.Content.Load<Model>(@"models\ground"), new Vector3(0, 0, 100), 4f));

            models.Add(new Bullet(
                Game.Content.Load<Model>(@"models\rabbids_models"), new Vector3(50, 30, 100), 15f, new Vector3(0, .5f, 0)));
            models.Add(new Bullet(
                Game.Content.Load<Model>(@"models\rabbids_models"), new Vector3(100, 30, 100), 15f, new Vector3(0, 0, .5f)));
            models.Add(new Bullet(
                Game.Content.Load<Model>(@"models\rabbids_models"), new Vector3(150, 30, 100), 15f, new Vector3(.5f, 0, .5f)));
            models.Add(new Bullet(
                Game.Content.Load<Model>(@"models\rabbids_models"), new Vector3(200, 30, 100), 15f, new Vector3(.5f, .5f, 0)));
            models.Add(new Bullet(
                Game.Content.Load<Model>(@"models\rabbids_models"), new Vector3(250, 30, 100), 15f, new Vector3(.5f, 0, 0)));


            base.LoadContent();
        }

        public override void Update(GameTime gameTime) {
            for (int i = 0; i < models.Count; i++) {
                models[i].Update();
            }
            UpdateShots();
            UpdateExplosions(gameTime);
            base.Update(gameTime);
        }
        protected void UpdateExplosions(GameTime gameTime) {
            // Loop through and update explosions
            for (int i = 0; i < explosions.Count; ++i) {
                explosions[i].Update(gameTime);
                // If explosion is finished, remove it
                if (explosions[i].IsDead) {
                    explosions.RemoveAt(i);
                    --i;
                }
            }
        }
        public override void Draw(GameTime gameTime) {
            foreach (BasicEntity be in models) {
                be.Draw(((Game1)Game).player);
            }

            foreach (BasicEntity bm in shots) {
                bm.Draw(((Game1)Game).player);
            }

            foreach (ParticleExplosion pe in explosions) {
                pe.Draw(((Game1)Game).player);
            }

            base.Draw(gameTime);
        }

        public void AddShot(Vector3 position, Vector3 direction) {
            shots.Add(new Bullet(
                Game.Content.Load<Model>(@"models\bullet"),
                position, 1.0f, direction));
        }

        protected void UpdateShots() {
            for (int i = 0; i < shots.Count; i++) {
                if (shots[i].GetWorld().Translation.X < bulletPosMIN.X) {
                    shots.RemoveAt(i);
                    i--;
                } else if (shots[i].GetWorld().Translation.Y < bulletPosMIN.Y) {
                    shots.RemoveAt(i);
                    i--;
                } else if (shots[i].GetWorld().Translation.Z < bulletPosMIN.Z) {
                    shots.RemoveAt(i);
                    i--;
                } else if (shots[i].GetWorld().Translation.Z > bulletPosMAX.X) {
                    shots.RemoveAt(i);
                    i--;
                } else if (shots[i].GetWorld().Translation.Y > bulletPosMAX.Y) {
                    shots.RemoveAt(i);
                    i--;
                } else if (shots[i].GetWorld().Translation.Z > bulletPosMAX.Z) {
                    shots.RemoveAt(i);
                    i--;
                } else {
                    shots[i].Update();
                    for (int j = 0; j < models.Count; j++) {
                        if (shots[i].CollidesWith(models[j].model,
                            models[j].GetWorld())) {

                            explosions.Add(new ParticleExplosion(GraphicsDevice,
    models[j].GetWorld().Translation,
    ((Game1)Game).rnd.Next(
        particleExplosionSettings.minLife,
        particleExplosionSettings.maxLife),
    ((Game1)Game).rnd.Next(
        particleExplosionSettings.minRoundTime,
        particleExplosionSettings.maxRoundTime),
    ((Game1)Game).rnd.Next(
        particleExplosionSettings.minParticlesPerRound,
        particleExplosionSettings.maxParticlesPerRound),
    ((Game1)Game).rnd.Next(
        particleExplosionSettings.minParticles,
        particleExplosionSettings.maxParticles),
    explosionColorsTexture, particleSettings,
    explosionEffect));
                            models.RemoveAt(j);
                            shots.RemoveAt(i);
                            i--;
                            break;
                        }
                    }
                }
            }
        }

    }
}
